; This is the final revision, designed to work with a 64K system ROM ; that has the CP/M code in the upper 16KB page (C000-FFFF). ; The NMI BASIC formerly placed there is now loaded by loading the ; standard Spectrum BASIC in DRAM0 and then injecting in it the NMI routine ; which is stored separately in the free space at the end of the upper ; 16KB system ROM page, after the CP/M code. Then 3 bytes are also modified ; starting at 0066 in the BASIC code. ; Lines that must be modified for different video memory address ; are marked with --------@@@ at the end (23 lines in total) ; Video memory starts at C000 for CoBra startup config (both 64K and 80K configs) ; and at 4000 for standard Spectrum (emulator to test this assembled code) ; Memory locations used for temporary storage of variables: ; $8000 = Current hardware config ($64 if 64K, $80 if 80K) ; $8080-$808F = checksum results for SYSTEM ROM area $0000-$3FFF ; $8090-$809F = checksum results for SYSTEM ROM area $4000-$7FFF ; $80A0-$80AF = checksum results for SYSTEM ROM area $8000-$BFFF ; $80B0-$80BF = checksum results for SYSTEM ROM area $C000-$FFFF CBASE EQU $0400 ; character definitions table, base address ; (the first 32 (20h) chars are non printable ; so we don't use them, therefore the space ; between 0400-04FF can be used for code) ORG $0000 DI LD A,$80 LD R,A ; set bit 7 of R to 1 -> PO to 1 LD SP,$0000 ; set stack at memory top CALL DELAY ; a delay to allow 8255 to come out of reset CALL DELAY ; a delay to allow 8255 to come out of reset LD A,$03 ; OUT ($E3),A ; Reset OUT ($EB),A ; and disable OUT ($F3),A ; Z80-CTC OUT ($FB),A ; channels. LD A,$92 ; Control word for 8255: Mode Set flag=active, ; Group A: Select Mode 0, ; Port A set to Input mode, ; Port C (upper half) set to Output Mode, ; Group B: Select Mode 0, ; Port B set to Input Mode, ; Port C (lower half) set to Output Mode OUT ($DF),A ; Send control word to 8255 LD A,$40 OUT ($FE),A ; write 40h to port C of 8255 ; (border black, "SO" to 0, "O5" to 0, ; "O6" to 1 to allow access to video memory ; in the 80K hw startup config) JR MAIN ;############# LOAD SYSTEM FROM ROM ####### ; input: A=00 -> bit 3 (TO=A15) -> OPUS+BASIC/DEVIL+NMI ; A=08 -> bit 7 (SO=A14) -> OPUS/BASIC DEVIL/NMI ; for OPUS: LD A,$00: CALL RS: LD A,$08: JP RS ; for BASIC: LD A,$00: CALL RS: LD A,$08: JP ST ; for DEVIL: LD A,$00: CALL ST: LD A,$08: JP RS ; for NMI: LD A,$00: CALL ST: LD A,$08: JP ST RS ADD A,$06 ; reset bit 3 (TO=A15=0) or 7 (SO=A14=0) JR SOTO ST ADD A,$07 ; set bit 3 (TO=A15=1) or 7 (SO=A14=1) SOTO CP $08 OUT ($DF),A RET C ; return if bit 3 processed SYS LD HL,$6000 LD DE,$E000 LD BC,$2000 LDIR ; copy system code upper half in upper half DRAM#0 if 64K RAM ;############# 80K BASIC CONFIG ######## ; This routine needs to be present at this address ($0038) ; in the BOOT ROM, for Spectrum programs to be loaded from disk ; and run in CP/M 80K with the standard "CP/M game loader". ORG $0038 LD HL,$4000 ; 4000 is the start addr of BASIC EPROM in the startup hw config LD DE,$8000 ; 8000 is the start addr of DRAM#0 in the startup hw config LD BC,$4000 ; 4000 is the length of the SPECTRUM BASIC code (16 KB) LDIR ; copy system code into DRAM#0 for 80K RAM NMISYS EXX ; HL' contains the final jump address LD A,$03 ; OUT ($E3),A ; OUT ($EB),A ; OUT ($F3),A ; OUT ($FB),A ; XOR A ; OUT ($FD),A ; OUT ($FE),A ; write 03 to port C of 8255 ; (set border to white, SO=0, O5=0, O6=0) LD R,A ; set bit 7 of R to 0, prepare for BASIC hardware configuration JP (HL) ; change hardware configuration with a jump to (HL) ; ############ MAIN CODE ############ ; ---------- DRAWING THE SCREEN ---------- MAIN LD HL,$8000 ; video mem is at C000 -------@@@ LD DE,$8001 ; video mem is at C000 -------@@@ LD BC,$7FFF LD (HL),0 LDIR LD HL,$D800 LD DE,$D801 LD BC,$300 LD (HL),$06 ; INK=yellow, PAPER=black LDIR LD HL,$DAE0 ; --- cfg info background ----@@@ LD DE,$DAE1 ; -------@@@ LD BC,$19 LD (HL),$05 ; INK=yellow, PAPER=black LDIR LD HL,$D842 ; --- title background -------@@@ LD DE,$D843 ; -------@@@ LD BC,$1B LD (HL),$16 ; INK=yellow, PAPER=red LDIR LD HL,$D8A2 ; --- 64K section title bg ---@@@ LD DE,$D8A3 ; -------@@@ LD BC,$0B LD (HL),$1E ; INK=yellow, PAPER=magenta LDIR LD HL,$D8B2 ; --- 80K section title bg ---@@@ LD DE,$D8B3 ; -------@@@ LD BC,$0B LD (HL),$0E ; INK=yellow, PAPER=blue LDIR LD HL,$1700 ; --- config info text LD DE,M_9 CALL MSG_PR ; ---------- START CONFIG DETECTION ---------- LD HL,MEM_T LD DE,$E000 ; if 80K hw config, this s/b in the VRAM (for "O6"=1) LD BC,$20 LDIR ; copy signature test string to $E000 LD A,$00 OUT ($FE),A ; write 00h to port C of 8255 ; (set "O6" to 0, if we are in 80K config then at ; E000 there s/b now DRAM#1 instead of VRAM) LD DE,MEM_T LD HL,$E000 LD BC,$20 SGV LD A,(DE) CPI JP PO,C64K ; config is 64K if entire signature string identical JR NZ,C80K ; config is 80K if anything is different INC DE JR SGV C64K LD HL,$171C ; --- configuration 64K LD DE,M_10 CALL MSG_PR LD HL,$D900 ; --- 64K section first item ---@@@ LD DE,$D901 ; ---------@@@ LD BC,$0E LD (HL),$86 ; INK=yellow, PAPER=black, BLINK LDIR LD HL,$DAFB ; --- config background --------@@@ LD DE,$DAFC ; ---------@@@ LD BC,$04 LD (HL),$1E ; INK=yellow, PAPER=magenta LDIR LD A,$64 LD ($8000),A ; (store computer config info at 8000) LD IX,(T_LC) ; position of top item in left column (color attr) LD IY,$01 LD A,$03 ; border magenta, "SO" to 0, "O5" to 0, "O6" to 0 OUT ($FE),A ; ("O6" to 1 not req'd for access to video memory ; in the 64K hw startup config) JR NXT5 C80K LD A,$41 ; border blue, "SO" to 0, "O5" to 0, OUT ($FE),A ; "O6" to 1 to allow access to video memory ; in the 80K hw startup config LD HL,$171C ; --- configuration 80K LD DE,M_11 CALL MSG_PR LD HL,$D911 ; --- 80K section first item ---@@@ LD DE,$D912 ; ---------@@@ LD BC,$0E LD (HL),$86 ; INK=yellow, PAPER=black, BLINK LDIR LD HL,$DAFB ; --- config background --------@@@ LD DE,$DAFC ; ---------@@@ LD BC,$04 LD (HL),$0E ; INK=yellow, PAPER=blue LDIR LD A,$80 LD ($8000),A ; (store computer config info at 8000) LD IX,(T_RC) ; position of top item in right column (color attr) LD IY,$11 ; ---------- END CONFIG DETECTION ---------- NXT5 LD HL,$0204 ; title LD DE,M_1 CALL MSG_PR LD HL,$0503 ; 64K section header LD DE,M_2 CALL MSG_PR LD HL,$0513 ; 80K section header LD DE,M_3 CALL MSG_PR LD HL,$0801 ; std boot (64k) LD DE,M_4 CALL MSG_PR LD HL,$0812 ; std boot (80k) LD DE,M_4 CALL MSG_PR LD HL,$0A01 ; std test (64k) LD DE,M_6 CALL MSG_PR LD HL,$0A12 ; std test (80k) LD DE,M_6 CALL MSG_PR LD HL,$0C01 ; homok test (64k) LD DE,M_7 CALL MSG_PR LD HL,$0C12 ; mastery boot (80k) LD DE,M_5 CALL MSG_PR ; ---------- KEYBOARD READING ---------- ; KBD LD A,($8000) CP $80 JR NZ,NOCPM LD A,$FE ; test row KA8 IN A,($FE) RLA RLA RLA ; test bit K5 (CTRL key) JR C,NOCPM LD A,$EF ; test row KA12 IN A,($FE) RRA ; test bit K0 (0 key) JP NC,CPM0 ; CP/M with drive 0 as default if CTRL+0 pressed RRA ; test bit K1 (9 key) JP NC,CPM1 ; CP/M with drive 1 as default if CTRL+9 pressed RRA ; test bit K2 (8 key) JP NC,CPM2 ; CP/M with drive 2 as default if CTRL+8 pressed RRA ; test bit K3 (7 key) JP NC,CPM3 ; CP/M with drive 3 as default if CTRL+7 pressed NOCPM LD A,$7F ; test row KA15 IN A,($FE) RLA RLA RLA ; test bit K5 (F4 key) CALL NC,CRC ; do system ROM checksums ; ********** ROM LOADING B.N.O.D *********** RLA ; test bit K4 (B key) JR NC,BASIC ; load Spectrum Basic RLA ; test bit K3 (N) JR NC,NMI ; load Spectrum Basic with NMI routine LD A,$DF ; test row KA13 IN A,($FE) RRA RRA ; test bit K1 (O key) JR NC,OPUS ; load OPUS LD A,$FD ; test row KA9 IN A,($FE) RRA RRA RRA ; test bit K2 (D key) JR NC,DEVIL ; load DEVIL ; ********** ROM LOADING 1,2,3,4 *********** LD A,$F7 ; test row KA11 IN A,($FE) RRA ; test bit K0 (1 key) JR NC,OPUS RRA ; test bit K1 (2 key) JR NC,BASIC RRA ; test bit K2 (3 key) JR NC,DEVIL RRA ; test bit K3 (4 key) JR NC,NMI ; ****************************************** LD A,$BF ; test row KA14 IN A,($FE) RRA ; check bit K0 (ENTER key) CALL NC,SEL ; select and run boot code LD A,$FE ; test row KA8 IN A,($FE) RRA ; check bit K0 (Caps Shift) JR C,KBD ; if CapsShift not pressed restart loop LD A,$EF ; test row KA12 IN A,($FE) RLA RLA RLA RLA ; test bit K4 (key 6, down arrow) PUSH AF CALL NC,DOWN POP AF RLA ; test bit K3 (key 7, up arrow) CALL NC,UP JR KBD ; ############ END MAIN CODE ############ ; ########## ROM SYSTEM LOADING ######### ; --------- using port C parallel load ;OPUS LD A,$00 ; SO=0, TO=0 ; JR LOAD ;BASIC LD A,$80 ; SO=1, TO=0 ; JR LOAD ;DEVIL LD A,$08 ; SO=0, TO=1 ; JR LOAD ;NMI LD A,$88 ; SO=1, TO=1 ; no longer valid, now TO=0 to load regular BASIC in which NMI code will be injected after ;LOAD OUT ($FE),A ; LD HL,$0000 ; EXX ; JP SYS ; -------- using port C BSR Mode OPUS XOR A CALL RS JR O_D BASIC XOR A CALL RS JR B_N DEVIL XOR A CALL ST O_D LD A,$08 LD HL,$0000 EXX JP RS B_N LD A,$08 LD HL,$0000 EXX JP ST ; Routine for NMI BASIC loading using a 64K SYSTEM ROM ; that has CP/M (12800 bytes) + NMI code in the last quarter ; (C000-FFFF, where NMI BASIC used to be) ; The NMI BASIC is now loaded by loading the regular BASIC ; and then injecting the NMI code on top of it. NMI LD A,$80 OUT ($FE),A ; same as BASIC, set bit 7 (SO=A14=1) and reset bit 3 (TO=A15=0) LD HL,$0000 EXX SYS1 LD HL,$6000 LD DE,$E000 LD BC,$2000 LDIR ; copy system code upper half in upper half DRAM#0 if 64K RAM ;############# 80K BASIC CONFIG ############# LD HL,$4000 ; 4000 is the start addr of BASIC EPROM in the startup hw config LD DE,$8000 ; 8000 is the start addr of DRAM#0 in the startup hw config LD BC,$4000 ; 4000 is the length of the SPECTRUM BASIC code (16 KB) LDIR ; copy system code into DRAM#0 for 80K RAM ; ############ NMI CODE INJECTION ########### LD A,$88 ; SO=1, TO=1, access the CP/M ROM page OUT ($FE),A LD HL,$720F ; NMI code address in the CP/M ROM page LD DE,$F86F ; NMI code injection start address in 64K config LD BC,$013C ; NMI code length LDIR LD HL,$720F ; NMI code address in the CP/M ROM page LD DE,$B86F ; NMI code injection start address in 80K config LD BC,$013C ; NMI code length LDIR LD HL,$8066 ; \ LD (HL),$C3 ; \ modify 3 bytes at $0066 in BASIC LD HL,$3880 ; / to call the NMI code injected LD ($8067),HL ; / JP NMISYS ; jump to already existing copy of code below (to save space) ; EXX ; HL' contains the final jump address ; LD A,$03 ; ; OUT ($E3),A ; ; OUT ($EB),A ; ; OUT ($F3),A ; ; OUT ($FB),A ; ; XOR A ; ; OUT ($FD),A ; ; OUT ($FE),A ; write 03 to port C of 8255 ; ; (set border to white, SO=0, O5=0, O6=0) ; LD R,A ; set bit 7 of R to 0, prepare for BASIC hardware configuration ; JP (HL) ; change hardware configuration with a jump to (HL) ; ; ######### CP/M ROM LOADING ######### CPM0 LD A,$00 ; default drive 0 JR CPM CPM1 LD A,$01 ; default drive 1 JR CPM CPM2 LD A,$02 ; default drive 2 JR CPM CPM3 LD A,$03 ; default drive 3 CPM LD B,$8A ; bit2=1 (BORDER=RED), bit3=TO=A15=1 and bit7=SO=A14=1 to select 16K SYSTEM ROM with CPM LD C,$FE ; port C address OUT (C),B ; set LD HL,$4000 LD DE,$8000 LD BC,$3200 LDIR LD HL,$8004 ; DSK Byte, location used as mailbox from BOOT to CP/M for user choice of default drive LD (HL),A ; set default CP/M logical drive LD HL,$0000 ; jump address in upcoming CP/M config LD A,$40 OUT ($FE),A ; set O6=1 for CP/M config XOR A LD R,A JP (HL) ; ############ CHAR_PRINT ############ ; INPUTS: ; H = row to print character (0-23) ; L = column to print character (0-31) ; C = character code to print CHR_PR PUSH HL PUSH DE PUSH BC PUSH AF LD DE,0 ; DE = final screen mem addr LD A,H LD B,3 L1 SRL A ; 0 -> A ->CY RR E ; CY -> E -> CY DJNZ L1 ; row nr in bits 7,6,5 of E LD A,E ADD A,L ; add E to L LD E,A ; store result in E ##### lower final screen addr LD A,H OR $C0 ; video mem is at C000 -------@@@ AND $F8 ; reset lower 3 bits LD D,A ; store result in D ##### upper final screen addr LD HL,CBASE ; character definitions base addr LD B,0 ; BC = character to print on 16 bit RL B ; reset CY RL C ; ] multiply RL B ; ] contents of BC RL C ; RL B ; RL C ; RL B ; ] by 8 ADD HL,BC ; HL = char addr in char table LD B,8 ; counter for 8 lines TV of a char L2 LD A,(HL) ;\ LD (DE),A ; | print INC HL ; | the INC D ; | character DJNZ L2 ;/ POP AF POP BC POP DE POP HL RET ; ############ MSG PRINT ############ ; INPUTS: ; H = start row to print message (0-23) ; L = start column to print message (0-31) ; DE = message start address (ends with $00) MSG_PR LD A,(DE) LD C,A LD A,0 CP C RET Z ; return if char code is 0 LD A,$1F CP L RET M ; return if out of screen CALL CHR_PR INC L INC DE JR MSG_PR ; ######## KEYBOARD NON-PRESSED TEST ######## KEY_NP LD A,$FE ; test row KA8 IN A,($FE) AND $3F CP $3F ; check if any key pressed JR NZ,KEY_NP ; if any key still pressed read kbd again LD A,$EF ; test row KA12 IN A,($FE) AND $3F CP $3F ; check if any key pressed JR NZ,KEY_NP ; if any key still pressed, read kbd again LD B,$03 DL1 CALL DELAY DJNZ DL1 RET ; ########## HEX2ASCII ######### ; INPUTS: ; A = byte to print as ASCII hex digits ; OUTPUTS: ; B = upper digit ascii ; C = lower digit ascii H2A LD B,A SRL B SRL B SRL B SRL B ; B=upper digit AND $0F LD C,A ; C=lower digit LD A,B CALL TRAN LD B,A ; B=upper hex digit as ascii LD A,C CALL TRAN LD C,A ; B=lower hex digit as ascii RET ; ###### translate 4-bit hex digit in A into ASCII value TRAN CP $0A ; if A=00...09 JR C,NXT3 ; skip next line ADD A,$07 NXT3 ADD A,$30 ; A=ascii index RET ; ########## HEXPRINT ########## ; INPUTS: ; H = row to print character (0-23) ; L = column to print character (0-31) ; B = upper digit ascii ; C = lower digit ascii HEX_PR LD A,C LD C,B CALL CHR_PR INC L LD C,A CALL CHR_PR INC L RET ; ######### CHECKSUM PROCEDURE ######### ; INPUTS: ; IX = storage start addr for checksums (2 bytes per 2KB checked) CHS PUSH AF PUSH BC PUSH DE PUSH HL EXX PUSH AF PUSH BC PUSH DE PUSH HL EXX ; LD IX,$8080 ; storage addr for checksums LD B,$08 ; loop counter LD HL,$4000 ; BASIC ROM start addr (HL=mem pointer) L2K PUSH BC ; <--- <--- <--- <--- <--- <--- <--- <--- <--- <--- <---| LD DE,$0800 ; | EXX ; ***** | LD HL,$0000 ; HL'=0000 to start, HL' stores CRC value | EXX ; ***** | LCH1 LD A,(HL) ; <--- <--- <--- <--- <--- <----| read from (4000) | EXX ; ***** | | LD B,$08 ; loop counter | | LD C,A ; C=data byte | | LCH2 RLC C ; CY = bit 7<--- <--- <---| | | SBC A,A ; A=00-CY | | | LD E,A ; E=00(bit7=0) or FF | | | LD A,L ; (loop starts w L'=00) | | | AND $40 ; | | | SUB $01 ; | | | SBC A,A ; A=00(Lbit6=1) or FF | | | XOR E ; | | | LD E,A ; E=00 if bit7!=Lbit6 | | | LD A,H ; (loop starts w H'=00) | | | AND $01 ; | | | SUB $01 ; | | | SBC A,A ; A=00(Hbit1=1) or FF | | | XOR E ; | | | LD E,A ; E=00 if [(Hbit1=1)&(bit7!=Lbit6)]||[(Hbit1=0)&(bit7=Lbit6)] LD A,H ; | | | AND $08 ; | | | SUB $01 ; | | | SBC A,A ; A=00(Hbit3=1) or FF | | | XOR E ; | | | LD E,A ; | | | LD A,H ; | | | AND $80 ; | | | SUB $01 ; | | | SBC A,A ; A=00(Hbit7=1) or FF | | | XOR E ; | | | RLCA ; | | | RL L ; | | | RL H ; | | | DJNZ LCH2 ; ---> 8 loops -----> --->| | | EXX ; ***** | | INC HL ; increment mem pointer | | DEC DE ; decrement loop counter | | LD A,D ;\ test if | | OR E ;/ DE=0000 | | JR NZ,LCH1 ; ---> ---> 800h loops ---> --->| | EXX ; ***** | LD (IX+0),H ; store high byte of checksum | LD (IX+1),L ; store low byte of checksum | PUSH AF PUSH BC LD HL,($8002) LD A,(IX+0) CALL H2A CALL HEX_PR LD A,(IX+1) CALL H2A CALL HEX_PR LD ($8002),HL POP BC POP AF INC IX ; | INC IX ; | EXX ; ***** | POP BC ; B = loop counter | DJNZ L2K ; ---> 8 loops -----> ---> ---> ---> ---> ---> ---> --->| EXX POP HL POP DE POP BC POP AF EXX POP HL POP DE POP BC POP AF RET ; ########### CHECKSUMS ########## CRC PUSH AF PUSH BC PUSH IX LD HL,$1000 ; ROM checksum message LD DE,M_12 CALL MSG_PR LD IX,$8080 LD A,($8000) CP $64 JR Z,CKS1 LD B,$41 ; TO=0,SO=0 select ROM 0000-3FFF (80K config) JR CKS2 CKS1 LD B,$43 ; TO=0,SO=0 select ROM 0000-3FFF (64K config) CKS2 LD HL,$1017 ; address range being checksumed, 0000-3FFF LD DE,M_13 CALL MSG_PR LD HL,$1200 LD ($8002),HL CALL DO1 ; do checksums for ROM 0000-3FFF, store at 8080-808F SET 7,B ; TO=0,SO=1 select ROM 4000-7FFF LD HL,$1017 ; address range being checksumed, 4000-7FFF LD DE,M_14 CALL MSG_PR LD HL,$1300 LD ($8002),HL CALL DO1 ; do checksums for ROM 4000-7FFF, store at 8090-809F RES 7,B SET 3,B ; TO=1,SO=0 select ROM 8000-BFFF LD HL,$1017 ; address range being checksumed, 8000-BFFF LD DE,M_15 CALL MSG_PR LD HL,$1400 LD ($8002),HL CALL DO1 ; do checksums for ROM 8000-BFFF, store at 80A0-80AF SET 7,B ; TO=1,SO=1 select ROM C000-FFFF LD HL,$1017 ; address range being checksumed, C000-FFFF LD DE,M_16 CALL MSG_PR LD HL,$1500 LD ($8002),HL CALL DO1 ; do checksums for ROM C000-FFFF, store at 80B0-80BF ; ---------- erase current range ----------- LD HL,$1017 ; address range being checksumed, C000-FFFF LD DE,M_18 CALL MSG_PR ; ---------- highlight groups of 4 digits ---------- LD HL,M_13 ; smart reuse of already available data LD BC,$04 LD DE,$DA44 ; ---------@@@ EXX LD B,$10 REP1 EXX PUSH HL PUSH BC LDIR POP BC POP HL INC DE INC DE INC DE INC DE EXX DJNZ REP1 EXX ; -------------------------------------------------- POP IX POP BC POP AF RET DO1 PUSH BC ; backup current ROM zone selection LD A,B OUT ($FE),A CALL CHS ; checksums for ROM 0000-4000 stored at 8080-808F POP BC ; restore current ROM zone selection RET ; ####### MOVE SELECTION UP ###### UP CALL KEY_NP PUSH IX LD A,($8000) CP $64 LD HL,T_LC JR Z,NXT6 LD HL,T_RC NXT6 POP BC LD A,C CP (HL) ; compare low byte of T_LC JR NZ,NXT1 ; skip fwd if diff INC HL LD A,B CP (HL) ; compare high byte of T_LC RET Z ; if already on top item, exit NXT1 PUSH IX POP HL LD D,H LD E,L INC DE LD BC,$0E LD (HL),$06 ; INK=yellow, PAPER=black, BLINK=OFF LDIR ; turn BLINK OFF PUSH IX POP HL LD A,(R_I) LD DE,0 LD E,A RLC D ; reset CY SBC HL,DE PUSH HL POP IX ; update IX with current pos of selected item DEC IY LD D,H LD E,L INC DE LD BC,$0E LD (HL),$86 ; INK=yellow, PAPER=black, BLINK LDIR ; turn BLINK ON RET ; ####### MOVE SELECTION DOWN ###### DOWN CALL KEY_NP PUSH IX LD A,($8000) CP $64 LD HL,B_LC JR Z,NXT7 LD HL,B_RC NXT7 POP BC LD A,C CP (HL) ; compare low byte of B_LC JR NZ,NXT2 ; skip fwd if diff INC HL LD A,B CP (HL) ; compare high byte of B_LC RET Z ; if already on bottom item, exit NXT2 PUSH IX POP HL LD D,H LD E,L INC DE LD BC,$0E LD (HL),$06 ; INK=yellow, PAPER=black, BLINK=OFF LDIR ; turn BLINK OFF PUSH IX POP HL LD A,(R_I) LD DE,0 LD E,A ADD HL,DE PUSH HL POP IX ; update IX with current pos of selected item INC IY LD D,H LD E,L INC DE LD BC,$0E LD (HL),$86 ; INK=yellow, PAPER=black, BLINK LDIR ; turn BLINK ON RET ; ########### BOOT SELECT ######## SEL PUSH BC ; backup BC PUSH IY POP BC LD A,C CP $01 JP Z,BOOT64 CP $02 JP Z,TEST64 CP $03 JP Z,HOMOK CP $11 JP Z,BOOT80 CP $12 JP Z,TEST64 CP $13 JP Z,MASTY POP BC ; restore BC RET BOOT64 EQU $0800 ; address of standard 64K boot BOOT80 EQU $1000 ; address of standard 80K boot HOMOK EQU $1800 ; address of HOMOK test (64K) TEST64 EQU $2000 ; address of STD test (64K) MASTY EQU $2800 ; address of MASTERY boot (80K) ; ########### MESSAGES ########### ORG $6E0 M_1 DEFM "COBRA BOOT CODE SELECTOR" DEFB 0 M_2 DEFM "64K CONFIG" DEFB 0 M_3 DEFM "80K CONFIG" DEFB 0 M_4 DEFM "STANDARD BOOT" DEFB 0 M_5 DEFM "MASTERY BOOT" DEFB 0 M_6 DEFM "STANDARD TEST" DEFB 0 M_7 DEFM "HOMOK TEST" DEFB 0 M_8 DEFM "MODIFIED BOOT" DEFB 0 M_9 DEFM "THIS COMPUTER'S CONFIG IS:" DEFB 0 M_10 DEFM "64K" DEFB 0 M_11 DEFM "80K" DEFB 0 M_12 DEFM "SYSTEM ROM CHECKSUM:" DEFB 0 M_13 DEFM "0000-3FFF" DEFB 0 M_14 DEFM "4000-7FFF" DEFB 0 M_15 DEFM "8000-BFFF" DEFB 0 M_16 DEFM "C000-FFFF" DEFB 0 M_17 DEFM "THIS BOOT ROM CHECKSUM:" DEFB 0 M_18 DEFM " " DEFB 0 ; ########### MEMORY TEST SIGNATURE ########### MEM_T DEFM "*COBRA*HARDWARE*CONFIG*DETECTOR*" ; ########### MENU SCREEN POSITIONS ########### T_LC DEFW $D900 ; top item left column (color attr start) -------@@@ T_RC DEFW $D911 ; top item right column (color attr start) ------@@@ ; ***** these are values for 4 items per menu ***** ;B_LC DEFW $D9C0 ; bottom item left column (color attr start) ----@@@ ;B_RC DEFW $D9D1 ; bottom item right column (color attr start) ---@@@ ; ***** these are values for 3 items per menu ***** B_LC DEFW $D980 ; bottom item left column (color attr start) ----@@@ B_RC DEFW $D991 ; bottom item right column (color attr start) ---@@@ R_I DEFB $40 ; row interval (color attr addr diff) ; ########### CHARACTER DEFINITIONS ########### ORG $500 C_SP DEFB 0,0,0,0,0,0,0,0 ORG $508 ; to save space, this little routine is placed between the SPACE and APOSTROPHE char definitions DELAY EXX LD BC,$1FFF LD DE,$9001 LD HL,$9000 LD (HL),0 LDIR EXX RET ORG $538 C_APST DEFB $18,$18,$10,$00,$00,$00,$00 DEFB 0 ORG $568 C_MINUS DEFB $00,$00,$00,$7E,$7E,$00,$00 DEFB 0 ORG $580 C_0 DEFB $3C,$42,$46,$6A,$72,$62,$3C DEFB 0 C_1 DEFB $18,$30,$50,$18,$18,$18,$18 DEFB 0 C_2 DEFB $3C,$42,$02,$1C,$70,$60,$7E DEFB 0 C_3 DEFB $3C,$42,$02,$1C,$06,$46,$3C DEFB 0 C_4 DEFB $40,$40,$48,$7E,$0C,$0C,$0C DEFB 0 C_5 DEFB $7C,$60,$60,$7C,$02,$02,$7C DEFB 0 C_6 DEFB $3C,$42,$40,$7C,$62,$62,$3C DEFB 0 C_7 DEFB $7E,$02,$02,$0E,$1C,$38,$70 DEFB 0 C_8 DEFB $3C,$62,$62,$3C,$62,$62,$3C DEFB 0 C_9 DEFB $3C,$62,$62,$3E,$02,$62,$3C DEFB 0 ORG $5D0 C_COLN DEFB $00,$18,$18,$00,$18,$18,$00 DEFB 0 ORG $608 C_A DEFB $3C,$42,$42,$62,$7E,$62,$62 DEFB 0 C_B DEFB $7C,$42,$42,$7C,$62,$62,$7C DEFB 0 C_C DEFB $3C,$42,$40,$60,$60,$62,$3C DEFB 0 C_D DEFB $7C,$42,$42,$62,$62,$62,$7C DEFB 0 C_E DEFB $7E,$40,$40,$78,$60,$60,$7E DEFB 0 C_F DEFB $7E,$40,$40,$7C,$60,$60,$60 DEFB 0 C_G DEFB $3C,$42,$40,$60,$6E,$66,$3C DEFB 0 C_H DEFB $42,$42,$42,$7E,$62,$62,$62 DEFB 0 C_I DEFB $3C,$10,$10,$18,$18,$18,$3C DEFB 0 C_J DEFB $1E,$04,$04,$0C,$6C,$6C,$38 DEFB 0 C_K DEFB $46,$44,$48,$70,$68,$64,$66 DEFB 0 C_L DEFB $40,$40,$40,$60,$60,$60,$7E DEFB 0 C_M DEFB $42,$66,$5E,$6A,$62,$62,$62 DEFB 0 C_N DEFB $42,$62,$52,$6A,$66,$62,$62 DEFB 0 C_O DEFB $3C,$42,$42,$62,$62,$62,$3C DEFB 0 C_P DEFB $7C,$42,$42,$62,$7C,$60,$60 DEFB 0 C_Q DEFB $3C,$42,$42,$62,$6A,$64,$3A DEFB 0 C_R DEFB $7C,$42,$42,$62,$7C,$6C,$66 DEFB 0 C_S DEFB $3C,$62,$60,$3C,$02,$62,$3C DEFB 0 C_T DEFB $7E,$10,$10,$18,$18,$18,$18 DEFB 0 C_U DEFB $42,$42,$42,$62,$62,$62,$3C DEFB 0 C_V DEFB $42,$42,$42,$62,$62,$34,$18 DEFB 0 C_W DEFB $42,$42,$4A,$6A,$6A,$76,$24 DEFB 0 C_X DEFB $62,$62,$34,$08,$34,$62,$62 DEFB 0 C_Y DEFB $42,$42,$42,$24,$18,$18,$18 DEFB 0 C_Z DEFB $7E,$04,$08,$10,$20,$60,$7E DEFB 0